home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / bixdos.arc / QUERY.PAS < prev    next >
Pascal/Delphi Source File  |  1986-11-24  |  10KB  |  306 lines

  1. program Query;
  2. { This program allows variables in the COMMAND environment area to be
  3.   redefined interactivly. Its primary use is in .BAT files. Due to the
  4.   way COMMAND allocates the environment segment is isn't easy to
  5.   create new variables or increase the length of the value of old ones.
  6.   Therefore the variable to be set by query MUST be initialized to a string
  7.   of its largest legal size before executing QUERY.
  8.  
  9.   Syntax:
  10.    QUERY [/R][/Y][/N][/U][/n1,n2] <varname> [<string>..[<string>]]
  11.  
  12.   Example of Usage:
  13.    SET ANSWER=*
  14.    QUERY /Y ANSWER Do you want to delete all backup files?
  15.    IF %ANSWER%==Y GOTO DELETEM
  16.    GOTO EXIT
  17.    SET FILE=*************
  18.    QUERY FILE Enter the file name.ext:
  19.  
  20.   Options:
  21.    /R            Response is required
  22.    /Y            Response must be either Y or N.
  23.    /N            Response must be an integer
  24.    /<n1>[,<n2>]  Response must be an integer range 1 ..<n1> or <n1>..<n2>
  25.    /U            Convert response to upper case
  26.                                                              }
  27.  
  28.  type
  29.    EnvBuff = record
  30.      Env: array[1..2048] of char;
  31.    end;
  32.    EnvironmentPointer = ^EnvBuff;
  33.    Str4 = string[4];
  34.    str8 = string[8];
  35.    str9 = string[9];
  36.    str32 = string[32];
  37.    str64 = string[132];
  38.  
  39. var
  40.  EnvPtr,SearchPtr:        EnvironmentPointer;
  41.  FirstChar, LastChar,
  42.  Index, VarLen, StringLen,
  43.  BufferLen, ParamIndex,Ival,
  44.  Source, Target, Count,
  45.  HighRange,LowRange,Col:  integer;
  46.  Setname,VarName,Option:  Str32;
  47.  NewVal:                  Str64;
  48.  EndOfEnv,Found,InOptions,
  49.  Yoption,Noption,Uoption,
  50.  Roption, RangeOption,
  51.  LegalResponse:           boolean;
  52.  
  53. begin
  54.  If ParamCount > 0 then
  55.    begin
  56.     ParamIndex := 0;
  57.     InOptions := True;
  58.     Yoption := false;
  59.     Noption := false;
  60.     Uoption := false;
  61.     Roption := false;
  62.     RangeOption := false;
  63.  
  64.     Repeat
  65.      begin
  66.        ParamIndex := ParamIndex + 1;
  67.        If ParamIndex > ParamCount then InOptions := False;
  68.        Option := ParamStr(ParamIndex);
  69.        If Option[1] = '/' then
  70.         begin
  71.          Index := 1;
  72.          While Index <= Length(Option) do
  73.           begin
  74.             If Option[Index] <> '/' then
  75.              Writeln('Error, options must be seperated by "/"s');
  76.             Index := Index + 1;
  77.             Case UpCase(Option[Index]) of
  78.               '/': ;
  79.               'Y': Yoption := true;
  80.               'N': Noption := true;
  81.               'U': Uoption := true;
  82.               'R': Roption := true;
  83.               '0'..'9': begin
  84.                  RangeOption := true;
  85.                  LowRange := 1;
  86.                  HighRange := 0;
  87.                  While ( (Option[Index] >= '0') and (Option[Index] <= '9') ) and
  88.                       (Index <= Length(Option)) do
  89.                    begin
  90.                      HighRange := 10*HighRange + ( Ord(Option[Index])-Ord('0'));
  91.                      Index := Index + 1;
  92.                    end;
  93.                  If Option[Index] = ',' then
  94.                    begin
  95.                      Index := Index + 1;
  96.                      LowRange := HighRange;
  97.                      HighRange := 0;
  98.                      While ( (Option[Index] >= '0') and (Option[Index] <= '9') ) and
  99.                           (Index <= Length(Option)) do
  100.                        begin
  101.                          HighRange := 10*HighRange + ( Ord(Option[Index])-Ord('0'));
  102.                          Index := Index + 1;
  103.                        end;
  104.                    end;
  105.                   If Index < Length(Option) then Index := Index - 1;
  106.                 end {RangeOption};
  107.               Else Writeln('Invalid option:',Option[Index]);
  108.             end {Case};
  109.            Index := Index + 1;
  110.           end;
  111.         end
  112.        Else
  113.         InOptions := false;
  114.      end;
  115.     Until not InOptions;
  116.  
  117.  
  118.  
  119.     { Get the variable name from the parameter field and convert it to
  120.       upper case as COMMAND does.                                     }
  121.     VarName := ParamStr(ParamIndex);
  122.     For Index := 1 to Length(VarName) do
  123.                                 VarName[Index] := UpCase(VarName[Index]);
  124.  
  125.     { Set up addressing so that the Env array is based in the segment the
  126.       command processor is using for variables. The command processor leaves a
  127.       pointer to a copy of the environment area in CS:2C              }
  128.     MemW[ Seg(EnvPtr):Ofs(EnvPtr)+2 ] := MemW[Cseg:$002C];
  129.     MemW[ Seg(EnvPtr):Ofs(EnvPtr) ] := 0;
  130.     BufferLen := 0;
  131.     Repeat BufferLen := BufferLen + 1 Until EnvPtr^.Env[BufferLen] = #$01;
  132.  
  133.     { Search through memory for the REAL environment area. This will be
  134.       identical to the copy COMMAND provided us. This search is pretty quick
  135.       because command allocates program memory against its memory. }
  136.     Found := False;
  137.     SearchPtr := EnvPtr;
  138.     Repeat
  139.       begin
  140.        MemW[Seg(SearchPtr):Ofs(SearchPtr)+2] :=
  141.                                MemW[Seg(SearchPtr):Ofs(SearchPtr)+2] - 1;
  142.        Col := 0;
  143.        Repeat Col := Col + 1;
  144.        Until (Col = BufferLen) or (EnvPtr^.Env[Col] <> SearchPtr^.Env[Col]);
  145.        If Col = BufferLen then Found := True;
  146.       end;
  147.     Until Found or (MemW[Seg(SearchPtr):Ofs(SearchPtr)+2] = $0000);
  148.     If Not Found then
  149.       begin
  150.         Writeln;
  151.         Writeln('COMMAND processor environment area not found in memory');
  152.         Halt;
  153.       end
  154.     Else
  155.       EnvPtr := SearchPtr;
  156.  
  157.  
  158.  
  159.  
  160.     With EnvPtr^ do
  161.       begin
  162.        Index := 1;
  163.        EndOfEnv := Env[1]=#$01;
  164.        EndOfEnv := False;
  165.        Found := False;
  166.  
  167.       { Scan the environment area for this variable name. Format expected here
  168.         is the variable name (in upper case) followed by an '=' then a
  169.         string terminated by and #$00 (ASCIIZ). Then end of environment is
  170.         indicated by a SOH (#$01) where variable name should begin.         }
  171.        While not EndOfEnv and not Found do
  172.          begin
  173.            Setname := '';
  174.            While ( Env[Index] <> '=' ) and ( Env[Index] <> #$00 ) do
  175.              begin
  176.                Setname := Setname + Env[Index];
  177.                Index := Index + 1;
  178.              end;
  179.  
  180.            If SetName = VarName then
  181.              Found := true
  182.            Else { skip this variables value }
  183.              Repeat Index := Index + 1 Until Env[Index] = #$00;
  184.  
  185.            Index := Index + 1;
  186.            EndOfEnv := Env[Index] = #$01;
  187.            If EndOfEnv then
  188.            Writeln('Error:',Varname,' must be SET before using query');
  189.          end;
  190.  
  191.       If Found then
  192.        begin
  193.         FirstChar := Index;
  194.         Repeat Index := Index + 1 Until Env[Index] = #$00;
  195.         LastChar := Index - 1;
  196.         StringLen := LastChar-FirstChar+1;
  197.  
  198.         LegalResponse := false;
  199.         Repeat
  200.           begin
  201.             Index := ParamIndex+1;
  202.             While Index <= ParamCount do
  203.               begin
  204.                Write(ParamStr(Index),' ');
  205.                Index := Index + 1;
  206.               end;
  207.             Read(NewVal);
  208.             If Uoption or Yoption then For Col := 1 to Length(NewVal) do
  209.                                   NewVal[Col] := UpCase(NewVal[Col]);
  210.             LegalResponse := True;
  211.  
  212.             If Yoption then
  213.              begin
  214.                If Length(NewVal) > 0 then NewVal := NewVal[1];
  215.                If ( NewVal <> 'N' ) and ( NewVal <> 'Y' ) then
  216.                  begin
  217.                    Writeln;
  218.                    Writeln('Answer either "YES" or "NO"');
  219.                    LegalResponse := False;
  220.                  end;
  221.              end;
  222.  
  223.             If Noption then
  224.               begin
  225.                 Col := 1;
  226.                 While Col <= Length(NewVal) do
  227.                 If (NewVal[Col] > '9') or (NewVal[Col] < '0') then
  228.                   begin
  229.                     LegalResponse := False;
  230.                     Col := Length(NewVal)+1;
  231.                     Writeln;
  232.                     Write('Response should be a number');
  233.                     Writeln;
  234.                   end
  235.                 Else
  236.                     Col := Col + 1;
  237.               end;
  238.  
  239.             If Roption and (Length(NewVal) = 0) then
  240.               begin
  241.                 LegalResponse := False;
  242.                 Writeln;
  243.                 Writeln('A response is required');
  244.                 Writeln;
  245.               end;
  246.  
  247.             If RangeOption then
  248.               begin
  249.                 Ival := 0;
  250.                 Col := 1;
  251.                 While Col <= Length( NewVal ) do
  252.                   begin
  253.                     If ( Newval[Col] > '9' ) or ( NewVal[Col] < '0' ) then
  254.                       begin
  255.                         Col := Length( NewVal ) + 1;
  256.                         Writeln;
  257.                         Writeln('Response should be a number');
  258.                         Writeln;
  259.                         LegalResponse := False;
  260.                       end
  261.                     Else
  262.                       begin
  263.                         Ival := Ival*10 + ( Ord(NewVal[Col]) - Ord('0') );
  264.                         Col := Col + 1;
  265.                       end;
  266.                   end;
  267.  
  268.                 If ( Ival > HighRange ) or ( Ival < LowRange ) then
  269.                   begin
  270.                     Writeln;
  271.                     Writeln('Answer must be in the range ',LowRange,'..',
  272.                              HighRange);
  273.                     Writeln;
  274.                     LegalResponse := False;
  275.                   end;
  276.               end;
  277.           end;
  278.         Until LegalResponse;
  279.  
  280.         { Truncate the input string if it is too long }
  281.         If Length(NewVal) > StringLen then NewVal := Copy(NewVal,1,StringLen);
  282.         { Now copy the new value to the environment area }
  283.         Col := 1;
  284.         Index := FirstChar;
  285.         While Col <= Length(NewVal) do
  286.          begin
  287.           Env[Index] := NewVal[Col];
  288.           Col := Col + 1;
  289.           Index := Index + 1;
  290.          end;
  291.         { If the new value is shorter that the string length then shift the
  292.           rest of the environment area down }
  293.         Count := BufferLen - LastChar - 1;
  294.         Source := LastChar + 1;
  295.         Target := Index;
  296.         For Index := 1 to Count do
  297.           begin
  298.             Env[Target] := Env[Source];
  299.             Source := Source + 1;
  300.             Target := Target + 1;
  301.           end;
  302.        end;
  303.      end;
  304.    end;
  305. end.
  306.